const axios = require('axios');
const db = require('../models');
const config = require('../config/wechat');
const logger = require('../utils/logger');
const cache = require('../utils/cache');
const { CallbackService } = require('./CallbackService');
class PushService {
  // 测试推送
  async testPush(openid, city) {
    try {
      // 查找或创建测试用户
      const user = await db.User.findOrCreate({
        where: { openid: `test_${openid}` },
        defaults: {
          openid: `test_${openid}`,
          subscribeTime: new Date(),
          status: 1
        }
      });

      // 创建测试订阅
      const [subscription] = await db.Subscription.findOrCreate({
        where: { userId: user[0].id, cityName: city },
        defaults: {
          userId: user[0].id,
          cityName: city,
          pushTime: '08:00',
          weatherEnabled: true,
          trafficEnabled: false,
          status: 1
        }
      });

      // 执行推送
      await this.pushWeather(user[0], subscription);

      // 创建推送记录
      await db.PushRecord.create({
        userId: user[0].id,
        subscriptionId: subscription.id,
        pushType: 'weather',
        content: '测试推送内容',
        pushTime: new Date(),
        status: 'success'
      });

      return true;
    } catch (err) {
      console.error('测试推送失败:', err);
      throw err;
    }
  }

  // 重试推送
  async retryPush(pushRecord) {
    try {
      // 根据推送类型调用不同的推送方法
      if (pushRecord.pushType === 'weather') {
        await this.pushWeather(pushRecord.User, pushRecord.Subscription);
      } else if (pushRecord.pushType === 'traffic') {
        await this.pushTraffic(pushRecord.User, pushRecord.Subscription);
      }

      // 更新推送记录状态
      await db.PushRecord.update({
        status: 'success',
        pushTime: new Date(),
        errorMsg: null
      }, {
        where: { id: pushRecord.id }
      });

      return true;
    } catch (err) {
      // 更新失败状态
      await db.PushRecord.update({
        status: 'failed',
        errorMsg: err.message
      }, {
        where: { id: pushRecord.id }
      });
      throw err;
    }
  }

  // 即时推送处理
  async sendInstantPush(user, content, callbackUrl) {
    const result = {
      successCount: 0,
      failCount: 0,
      callbackUrl,
      pushId: `instant_${Date.now()}`,
      details: []
    };

    try {
      // 检查推送权限
      if (!user.pushEnabled) {
        logger.info('推送跳过：用户已禁用推送', { userId: user.id });
        return result;
      }

      // 检查免打扰时段
      if (this.isQuietHours(user)) {
        logger.info('推送跳过：处于免打扰时段', { userId: user.id });
        return result;
      }

      // 发送即时消息
      await this.sendWechatMessage(user.openid, content || '您有一条新通知');
      result.successCount++;

      // 记录推送
      await db.PushRecord.create({
        userId: user.id,
        pushType: 'instant',
        content: content,
        pushTime: new Date(),
        status: 'success'
      });
    } catch (err) {
      logger.error('即时推送失败', {
        userId: user.id,
        error: err.message
      });
      result.failCount++;

      // 记录失败
      await db.PushRecord.create({
        userId: user.id,
        pushType: 'instant',
        content: content,
        pushTime: new Date(),
        status: 'failed',
        errorMsg: err.message
      });
    }

    return result;
  }

  // 正式推送接口（多服务整合）
  async sendOfficialPush(userId, pushType = 'scheduled', content) {
    try {
      // 获取用户和订阅信息
      const user = await db.User.findByPk(userId, {
        include: [{
          model: db.Subscription,
          as: 'subscriptions'
        }]
      });

      if (!user || !user.subscriptions || user.subscriptions.length === 0) {
        logger.warn('推送跳过：用户无有效订阅', { userId });
        return;
      }

      // 检查推送权限
      if (!user.pushEnabled) {
        logger.info('推送跳过：用户已禁用推送', { userId });
        return;
      }

      // 检查免打扰时段
      if (this.isQuietHours(user)) {
        logger.info('推送跳过：处于免打扰时段', { userId });
        return;
      }

      // 处理每个订阅
      for (const subscription of user.subscriptions) {
        if (subscription.status !== 1) continue; // 只处理启用状态的订阅

        // 根据订阅服务类型发送推送
        if (subscription.weatherEnabled) {
          await this.pushWeather(user, subscription);
        }
        if (subscription.trafficEnabled) {
          await this.pushTraffic(user, subscription);
        }
        // 其他服务推送...
      }
    } catch (err) {
      logger.error('正式推送失败', {
        userId,
        error: err.message,
        stack: err.stack
      });
      throw err;
    }
  }

  // 推送天气信息（带验证）
  async pushWeather(user, subscription) {
    // 检查免打扰时段
    if (this.isQuietHours(user)) {
      logger.info('推送跳过：处于免打扰时段', {
        userId: user.id,
        pushTime: new Date()
      });
      return;
    }

    // 检查用户是否启用推送
    if (!user.pushEnabled) {
      logger.info('推送跳过：用户已禁用推送', {
        userId: user.id
      });
      return;
    }

    // 检查推送频率限制
    const lastPush = await db.PushRecord.findOne({
      where: {
        userId: user.id,
        pushType: 'weather',
        status: 'success'
      },
      order: [['pushTime', 'DESC']]
    });

    if (lastPush && (new Date() - lastPush.pushTime) < 30 * 60 * 1000) {
      logger.warn('推送跳过：频率限制', {
        userId: user.id,
        lastPushTime: lastPush.pushTime
      });
      return;
    }

    // 获取天气数据
    const weatherData = await this.getWeatherData(subscription.cityName);

    // 根据模板类型格式化消息
    const message = this.formatMessage(
      weatherData,
      subscription.templateType || 'default'
    );

    // 验证消息长度
    if (message.length > 500) {
      logger.error('消息过长', {
        userId: user.id,
        messageLength: message.length
      });
      throw new Error('消息内容超过500字符限制');
    }

    // 发送消息
    await this.sendWechatMessage(user.openid, message);

    // 记录推送
    await db.PushRecord.create({
      userId: user.id,
      subscriptionId: subscription.id,
      pushType: 'weather',
      content: message,
      pushTime: new Date(),
      status: 'success'
    });
  }

  // 检查是否处于免打扰时段
  isQuietHours(user) {
    if (!user.quietHoursEnabled) return false;

    const now = new Date();
    const [startHour, startMin] = user.quietHoursStart.split(':').map(Number);
    const [endHour, endMin] = user.quietHoursEnd.split(':').map(Number);

    const startTime = new Date();
    startTime.setHours(startHour, startMin, 0, 0);

    const endTime = new Date();
    endTime.setHours(endHour, endMin, 0, 0);

    return now >= startTime && now <= endTime;
  }

  // 根据模板格式化消息
  formatMessage(data, templateType) {
    const templates = {
      default: `今日${data.city}天气：${data.weather}，温度${data.temp}℃`,
      simple: `${data.city} ${data.weather} ${data.temp}℃`,
      detailed: `【${data.city}天气预报】\n天气状况：${data.weather}\n当前温度：${data.temp}℃\n湿度：${data.humidity}%\n风力：${data.wind}`
    };

    return templates[templateType] || templates.default;
  }

  // 推送限行信息
  async pushTraffic(user, subscription) {
    // 这里实现限行推送逻辑
    // 示例代码，实际应根据项目需求实现
    const trafficData = await this.getTrafficData(subscription.cityName);
    await this.sendWechatMessage(user.openid, trafficData);
  }

  // 获取天气数据
  async getWeatherData(city) {
    // 调用天气API获取数据
    // 示例代码，实际应根据项目需求实现
    return `今日${city}天气：晴，温度20-28℃`;
  }

  // 获取限行数据
  async getTrafficData(city) {
    // 调用限行API获取数据
    // 示例代码，实际应根据项目需求实现
    return `今日${city}限行尾号：1和6`;
  }

  // 发送微信消息（带回调通知）
  async sendWechatMessage(openid, content, callbackUrl) {
    try {
      const response = await axios.post('https://api.weixin.qq.com/cgi-bin/message/custom/send', {
        touser: openid,
        msgtype: 'text',
        text: {
          content: content
        }
      }, {
        params: {
          access_token: await this.getAccessToken()
        }
      });

      if (response.data.errcode !== 0) {
        throw new Error(response.data.errmsg);
      }

      // 发送成功回调
      if (callbackUrl) {
        await CallbackService.notifyPushResult({
          pushId: `msg_${Date.now()}`,
          status: 'success',
          openid,
          contentLength: content.length,
          callbackUrl
        });
      }

      return true;
    } catch (err) {
      // 发送失败回调
      if (callbackUrl) {
        await CallbackService.notifyPushResult({
          pushId: `msg_${Date.now()}`,
          status: 'failed',
          openid,
          error: err.message,
          callbackUrl
        });
      }
      throw err;
    }
  }

  // 获取微信access_token（带缓存）
  async getAccessToken() {
    const cacheKey = 'wechat_access_token';
    const cachedToken = await cache.get(cacheKey);

    if (cachedToken) {
      return cachedToken;
    }

    try {
      const response = await axios.get('https://api.weixin.qq.com/cgi-bin/token', {
        params: {
          grant_type: 'client_credential',
          appid: config.appId,
          secret: config.appSecret
        }
      });

      const { access_token, expires_in } = response.data;
      // 缓存token，提前5分钟过期
      await cache.set(cacheKey, access_token, expires_in - 300);

      return access_token;
    } catch (err) {
      logger.error('获取access_token失败', {
        error: err.message,
        response: err.response?.data,
        stack: err.stack
      });
      throw new Error('获取微信access_token失败');
    }
  }
}

module.exports = new PushService();